home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / gfx / 3d / irit50src.lha / irit5 / bool_lib / bool-hi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-30  |  32.4 KB  |  814 lines

  1. /*****************************************************************************
  2. *   "Irit" - the 3d (not only polygonal) solid modeller.             *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 0.2, Mar. 1990   *
  5. ******************************************************************************
  6. *   Module to handle the high level Boolean operations. The other modules    *
  7. * should only call this module to perform Boolean operations. All the        *
  8. * operations are none-destructives, meaning the given data is not modified.  *
  9. *   Note all the polygons of the two given objects must be convex, and the   *
  10. * returned object will also have only convex polygons!                 *
  11. *****************************************************************************/
  12.  
  13. /* #define DEBUG2             If defined, defines some printing routines. */
  14.  
  15. #include <stdio.h>
  16. #include <ctype.h>
  17. #include <math.h>
  18. #include <string.h>
  19. #include <signal.h>
  20. #include "irit_sm.h"
  21. #include "allocate.h"
  22. #include "attribut.h"
  23. #include "bool_loc.h"
  24. #include "convex.h"
  25. #include "poly_cln.h"
  26. #include "geomat3d.h"
  27.  
  28. int BoolHandleCoplanarPoly = FALSE,     /* Whether to handle coplanar polys. */
  29.     BoolOutputInterCurve = FALSE;    /* Kind of output from Boolean oper. */
  30.  
  31. static jmp_buf LclLongJumpBuffer;         /* Used in fatal Boolean error. */
  32. static int FatalErrorType;             /* Type of fatal Boolean error. */
  33. static BoolOperType BooleanOperation;        /* One of BOOL_OPER_OR, etc. */
  34.  
  35. static IPObjectStruct *BooleanCombineThreeObjs(IPObjectStruct *PObj1,
  36.                            IPObjectStruct *PObj2,
  37.                            IPObjectStruct *PObj3);
  38. static IPObjectStruct *BooleanCoplanar(IPObjectStruct *PObj1,
  39.                        IPObjectStruct *PObj2,
  40.                        BoolOperType BoolOper);
  41. static IPObjectStruct *VerifyBooleanInput(IPObjectStruct *PObj1,
  42.                       IPObjectStruct *PObj2,
  43.                       BoolOperType Oper);
  44. static IPPolygonStruct *ComputeRotatedPolys(IPPolygonStruct *Pl,
  45.                         int CopyPl,
  46.                         MatrixType RotMat);
  47.  
  48. static void BooleanFPE(int Type);
  49.  
  50. #ifdef DEBUG2
  51. static void PrintVrtxList(IPVertexStruct *V);
  52. #endif /* DEBUG2 */
  53.  
  54. /*****************************************************************************
  55. * DESCRIPTION:                                                               *
  56. *   Verify input for Booleans. Ret. NULL if OK, otherwise an obj to return.  *
  57. *                                                                            *
  58. * PARAMETERS:                                                                *
  59. *   PObj1:     First object for to be performed Boolean.                     *
  60. *   PObj2:     Second object for to be performed Boolean.                    *
  61. *   Oper:      Type of operation (and, or, etc.).                            *
  62. *                                                                            *
  63. * RETURN VALUE:                                                              *
  64. *   IPObjectStruct:      NULL if Boolean operation can/should be performed.  *
  65. *                        Otherwise, an object to return as Boolean result.   *
  66. *****************************************************************************/
  67. static IPObjectStruct *VerifyBooleanInput(IPObjectStruct *PObj1,
  68.                       IPObjectStruct *PObj2,
  69.                       BoolOperType Oper)
  70. {
  71.     IPObjectStruct *PObj;
  72.     IPPolygonStruct *Pl;
  73.  
  74.     BooleanOperation = Oper;
  75.  
  76.     if (!IP_IS_POLY_OBJ(PObj1) || (PObj2 != NULL && !IP_IS_POLY_OBJ(PObj2)))
  77.     IritFatalError("Boolean: operation on non polygonal object(s).");
  78.  
  79.     signal(SIGFPE, BooleanFPE);         /* Will trap floating point errors. */
  80.  
  81.     switch (Oper) {
  82.     case BOOL_OPER_OR:
  83.         if (IP_IS_POLYLINE_OBJ(PObj1) && IP_IS_POLYLINE_OBJ(PObj2)) {
  84.         if (PObj1 -> U.Pl == NULL)
  85.             PObj = CopyObject(NULL, PObj2, FALSE);
  86.         else {
  87.             PObj = CopyObject(NULL, PObj1, FALSE);
  88.             Pl = IritPrsrGetLastPoly(PObj -> U.Pl);
  89.             Pl -> Pnext = CopyPolygonList(PObj2 -> U.Pl);
  90.         }
  91.             return PObj;
  92.         }
  93.     case BOOL_OPER_AND:
  94.     case BOOL_OPER_SUB:
  95.     case BOOL_OPER_CUT:
  96.     case BOOL_OPER_MERGE:
  97.     case BOOL_OPER_NEG:
  98.             if (IP_IS_POLYLINE_OBJ(PObj1) ||
  99.         (PObj2 != NULL && IP_IS_POLYLINE_OBJ(PObj2))) {
  100.                 IritWarningError(
  101.         "Boolean: illegal operation on mixed polygon/line geometric object(s).");
  102.         PObj = GenPolyObject("", NULL, NULL);
  103.         return PObj;
  104.             }
  105.  
  106.         if (Oper != BOOL_OPER_NEG) {
  107.             ConvexPolyObject(PObj1);/* Make sure all polygons are convex.*/
  108.             ConvexPolyObject(PObj2);
  109.         }
  110.  
  111.         return NULL;
  112.     default:
  113.             IritFatalError("Boolean: undefined Boolean operation.");
  114.             return NULL;                 /* Make warning silent. */
  115.     }
  116. }
  117.  
  118. /*****************************************************************************
  119. * DESCRIPTION:                                                               M
  120. *   Performs a Boolean OR between two objects.                     M
  121. *                                                                            *
  122. * PARAMETERS:                                                                M
  123. *   PObj1:    First object to perform the Boolean operation on.              M
  124. *   PObj2:    Second object to perform the Boolean operation on.             M
  125. *                                                                            *
  126. * RETURN VALUE:                                                              M
  127. *   IPObjectStruct: The result of the Boolean operation.                     M
  128. *                                                                            *
  129. * KEYWORDS:                                                                  M
  130. *   BooleanOR, Booleans                                                      M
  131. *****************************************************************************/
  132. IPObjectStruct *BooleanOR(IPObjectStruct *PObj1, IPObjectStruct *PObj2)
  133. {
  134.     IPObjectStruct *PObj;
  135.     IPPolygonStruct *Pl;
  136.  
  137.     if ((PObj = VerifyBooleanInput(PObj1, PObj2, BOOL_OPER_OR)) != NULL)
  138.     return PObj;
  139.     else {
  140.     if (setjmp(LclLongJumpBuffer) == 0) { /* Its the setjmp itself call! */
  141.         signal(SIGFPE, BooleanFPE);     /* Will trap floating point errors. */
  142.         if (BoolOutputInterCurve)
  143.         PObj = BooleanLow1Out2(PObj1, PObj2);/* Ret intersection crv.*/
  144.         else
  145.         PObj = BooleanCombineThreeObjs(BooleanLow1Out2(PObj1, PObj2),
  146.                            BooleanLow1Out2(PObj2, PObj1),
  147.                            BooleanCoplanar(PObj1, PObj2,
  148.                                    BOOL_OPER_OR));
  149.  
  150.     }
  151.     else {
  152.         /* We gain control from fatal error long jump - usually we should*/
  153.         /* return empty object, but if error is no intersection between  */
  154.         /* the two objects, we assume they have no common volume and     */
  155.         /* return a new object consists of the concat. of all polygons!  */
  156.         if (FatalErrorType != FTL_BOOL_NO_INTER) {
  157.         PObj = GenPolyObject("", NULL, NULL);/* Return empty object. */
  158.         }
  159.         else {
  160.         if (PObj1 -> U.Pl == NULL)
  161.             PObj = CopyObject(NULL, PObj2, FALSE);
  162.         else {
  163.             PObj = CopyObject(NULL, PObj1, FALSE);/* Copy Obj1 polys.*/
  164.             Pl = PObj -> U.Pl;
  165.             while (Pl -> Pnext) Pl = Pl -> Pnext;
  166.             Pl -> Pnext = CopyPolygonList(PObj2 -> U.Pl);/*Obj2 poly.*/
  167.         }
  168.         }
  169.     }
  170.     }
  171.  
  172.     return PObj;
  173. }
  174.  
  175. /*****************************************************************************
  176. * DESCRIPTION:                                                               M
  177. *   Performs a Boolean AND between two objects.                     M
  178. *                                                                            *
  179. * PARAMETERS:                                                                M
  180. *   PObj1:    First object to perform the Boolean operation on.              M
  181. *   PObj2:    Second object to perform the Boolean operation on.             M
  182. *                                                                            *
  183. * RETURN VALUE:                                                              M
  184. *   IPObjectStruct: The result of the Boolean operation.                     M
  185. *                                                                            *
  186. * KEYWORDS:                                                                  M
  187. *   BooleanAND, Booleans                                                     M
  188. *****************************************************************************/
  189. IPObjectStruct *BooleanAND(IPObjectStruct *PObj1, IPObjectStruct *PObj2)
  190. {
  191.     IPObjectStruct *PObj;
  192.  
  193.     if ((PObj = VerifyBooleanInput(PObj1, PObj2, BOOL_OPER_AND)) != NULL)
  194.     return PObj;
  195.     else {
  196.     if (setjmp(LclLongJumpBuffer) == 0) { /* Its the setjmp itself call! */
  197.         signal(SIGFPE, BooleanFPE);     /* Will trap floating point errors. */
  198.         if (BoolOutputInterCurve)
  199.         PObj = BooleanLow1In2(PObj1, PObj2);/* Ret intersection crv. */
  200.         else
  201.         PObj = BooleanCombineThreeObjs(BooleanLow1In2(PObj1, PObj2),
  202.                            BooleanLow1In2(PObj2, PObj1),
  203.                            BooleanCoplanar(PObj1, PObj2,
  204.                                    BOOL_OPER_AND));
  205.  
  206.     }
  207.     else {/* We gain control from fatal error long jump - ret empty obj. */
  208.         PObj = GenPolyObject("", NULL, NULL);
  209.     }
  210.     }
  211.  
  212.     return PObj;
  213. }
  214.  
  215. /*****************************************************************************
  216. * DESCRIPTION:                                                               M
  217. *   Performs a Boolean SUBtracion between two objects.                 M
  218. *                                                                            *
  219. * PARAMETERS:                                                                M
  220. *   PObj1:    First object to perform the Boolean operation on.              M
  221. *   PObj2:    Second object to perform the Boolean operation on.             M
  222. *                                                                            *
  223. * RETURN VALUE:                                                              M
  224. *   IPObjectStruct: The result of the Boolean operation.                     M
  225. *                                                                            *
  226. * KEYWORDS:                                                                  M
  227. *   BooleanSUB, Booleans                                                     M
  228. *****************************************************************************/
  229. IPObjectStruct *BooleanSUB(IPObjectStruct *PObj1, IPObjectStruct *PObj2)
  230. {
  231.     IPObjectStruct *PObj, *PTemp, *PTempRev;
  232.  
  233.     if ((PObj = VerifyBooleanInput(PObj1, PObj2, BOOL_OPER_SUB)) != NULL)
  234.     return PObj;
  235.     else {
  236.     if (setjmp(LclLongJumpBuffer) == 0) { /* Its the setjmp itself call! */
  237.         signal(SIGFPE, BooleanFPE);     /* Will trap floating point errors. */
  238.         /* The 1 in 2 must be reversed (the inside/outside orientation): */
  239.         if (BoolOutputInterCurve) {
  240.         PObj = BooleanLow1In2(PObj2, PObj1);/* Ret intersection crv. */
  241.         }
  242.         else {
  243.         PTemp = BooleanLow1In2(PObj2, PObj1);
  244.         PTempRev = BooleanNEG(PTemp);
  245.         IPFreeObject(PTemp);
  246.  
  247.         PObj = BooleanCombineThreeObjs(BooleanLow1Out2(PObj1, PObj2),
  248.                            PTempRev,
  249.                            BooleanCoplanar(PObj1, PObj2,
  250.                                    BOOL_OPER_SUB));
  251.         }
  252.     }
  253.     else {/* We gain control from fatal error long jump - ret empty obj. */
  254.         PObj = GenPolyObject("", NULL, NULL);
  255.     }
  256.     }
  257.  
  258.     return PObj;
  259. }
  260.  
  261. /*****************************************************************************
  262. * DESCRIPTION:                                                               M
  263. *   Performs a Boolean CUT between two objects.                     M
  264. *                                                                            *
  265. * PARAMETERS:                                                                M
  266. *   PObj1:    First object to perform the Boolean operation on.              M
  267. *   PObj2:    Second object to perform the Boolean operation on.             M
  268. *                                                                            *
  269. * RETURN VALUE:                                                              M
  270. *   IPObjectStruct: The result of the Boolean operation.                     M
  271. *                                                                            *
  272. * KEYWORDS:                                                                  M
  273. *   BooleanCUT, Booleans                                                     M
  274. *****************************************************************************/
  275. IPObjectStruct *BooleanCUT(IPObjectStruct *PObj1, IPObjectStruct *PObj2)
  276. {
  277.     IPObjectStruct *PObj;
  278.  
  279.     if ((PObj = VerifyBooleanInput(PObj1, PObj2, BOOL_OPER_CUT)) != NULL)
  280.     return PObj;
  281.     else {
  282.     if (setjmp(LclLongJumpBuffer) == 0) { /* Its the setjmp itself call! */
  283.         signal(SIGFPE, BooleanFPE);     /* Will trap floating point errors. */
  284.         /* The 1 in 2 must be reversed (the inside/outside orientation): */
  285.         if (BoolOutputInterCurve) {
  286.         PObj = BooleanLow1In2(PObj2, PObj1);/* Ret intersection crv. */
  287.         }
  288.         else {
  289.         PObj = BooleanLow1Out2(PObj1, PObj2);
  290.         }
  291.     }
  292.     else {/* We gain control from fatal error long jump - ret empty obj. */
  293.         PObj = GenPolyObject("", NULL, NULL);
  294.     }
  295.     }
  296.  
  297.     return PObj;
  298. }
  299.  
  300. /*****************************************************************************
  301. * DESCRIPTION:                                                               M
  302. *   Performs a Boolean Inside CUT between two objects.                 M
  303. *                                                                            *
  304. * PARAMETERS:                                                                M
  305. *   PObj1:    First object to perform the Boolean operation on.              M
  306. *   PObj2:    Second object to perform the Boolean operation on.             M
  307. *                                                                            *
  308. * RETURN VALUE:                                                              M
  309. *   IPObjectStruct: The result of the Boolean operation.                     M
  310. *                                                                            *
  311. * KEYWORDS:                                                                  M
  312. *   BooleanICUT, Booleans                                                    M
  313. *****************************************************************************/
  314. IPObjectStruct *BooleanICUT(IPObjectStruct *PObj1, IPObjectStruct *PObj2)
  315. {
  316.     IPObjectStruct *PObj;
  317.  
  318.     if ((PObj = VerifyBooleanInput(PObj1, PObj2, BOOL_OPER_CUT)) != NULL)
  319.     return PObj;
  320.     else {
  321.     if (setjmp(LclLongJumpBuffer) == 0) { /* Its the setjmp itself call! */
  322.         signal(SIGFPE, BooleanFPE);     /* Will trap floating point errors. */
  323.         /* The 1 in 2 must be reversed (the inside/outside orientation): */
  324.         if (BoolOutputInterCurve) {
  325.         PObj = BooleanLow1In2(PObj2, PObj1);/* Ret intersection crv. */
  326.         }
  327.         else {
  328.         PObj = BooleanLow1In2(PObj1, PObj2);
  329.         }
  330.     }
  331.     else {/* We gain control from fatal error long jump - ret empty obj. */
  332.         PObj = GenPolyObject("", NULL, NULL);
  333.     }
  334.     }
  335.  
  336.     return PObj;
  337. }
  338.  
  339. /*****************************************************************************
  340. * DESCRIPTION:                                                               M
  341. *   Performs a Boolean MERGE between two objects.                 M
  342. *                                                                            *
  343. * PARAMETERS:                                                                M
  344. *   PObj1:    First object to perform the Boolean operation on.              M
  345. *   PObj2:    Second object to perform the Boolean operation on.             M
  346. *                                                                            *
  347. * RETURN VALUE:                                                              M
  348. *   IPObjectStruct: The result of the Boolean operation.                     M
  349. *                                                                            *
  350. * KEYWORDS:                                                                  M
  351. *   BooleanMERGE, Booleans                                                   M
  352. *****************************************************************************/
  353. IPObjectStruct *BooleanMERGE(IPObjectStruct *PObj1, IPObjectStruct *PObj2)
  354. {
  355.     IPObjectStruct *PObj;
  356.     IPPolygonStruct *Pl;
  357.  
  358.     if ((PObj = VerifyBooleanInput(PObj1, PObj2, BOOL_OPER_MERGE)) != NULL)
  359.     return PObj;
  360.     else {
  361.     if (PObj1 -> U.Pl == NULL)
  362.             PObj = CopyObject(NULL, PObj2, FALSE);
  363.         else {
  364.             PObj = CopyObject(NULL, PObj1, FALSE);       /* Copy Obj1 polys. */
  365.         Pl = PObj -> U.Pl;
  366.         while (Pl -> Pnext) Pl = Pl -> Pnext;
  367.         Pl -> Pnext = CopyPolygonList(PObj2 -> U.Pl);     /* Obj2 polys. */
  368.     }
  369.     }
  370.  
  371.     return PObj;
  372. }
  373.  
  374. /*****************************************************************************
  375. * DESCRIPTION:                                                               M
  376. *   Performs a Boolean NEG between two objects.                     M
  377. *   Negation is simply reversing the direction of the plane equation of each M
  378. * polygon - the simplest Boolean operation...                     M
  379. *                                                                            *
  380. * PARAMETERS:                                                                M
  381. *   PObj:    Object to negate.                             M
  382. *                                                                            *
  383. * RETURN VALUE:                                                              M
  384. *   IPObjectStruct: The result of the Boolean operation.                     M
  385. *                                                                            *
  386. * KEYWORDS:                                                                  M
  387. *   BooleanNEG, Booleans                                                     M
  388. *****************************************************************************/
  389. IPObjectStruct *BooleanNEG(IPObjectStruct *PObj)
  390. {
  391.     int i;
  392.     IPObjectStruct *PTemp;
  393.     IPPolygonStruct *Pl;
  394.     IPVertexStruct *V;
  395.  
  396.     if ((PTemp = VerifyBooleanInput(PObj, NULL, BOOL_OPER_NEG)) != NULL)
  397.     return PTemp;
  398.     else {
  399.     PTemp = CopyObject(NULL, PObj, FALSE); /* Make fresh copy of object. */
  400.  
  401.     /* Scans all polygons and reverse plane equation and their vetrex    */
  402.     /* list (cross prod. of consecutive edges must be in normal dir.).   */
  403.     Pl = PTemp -> U.Pl;
  404.     while (Pl != NULL) {
  405.         for (i = 0; i < 4; i++)
  406.             Pl -> Plane[i] = (-Pl -> Plane[i]);
  407.         IP_RST_CONVEX_POLY(Pl);
  408.  
  409.         /* Invert vertices normals as well. */
  410.         V = Pl -> PVertex;
  411.         do {
  412.         PT_SCALE(V -> Normal, -1.0);
  413.         V = V -> Pnext;
  414.         }
  415.         while (V != NULL && V != Pl -> PVertex);
  416.  
  417.         /* And reverse the order of the vertices. */
  418.         IritPrsrReverseVrtxList(Pl);
  419.  
  420.         Pl = Pl -> Pnext;
  421.     }
  422.     }
  423.  
  424.     return PTemp;
  425. }
  426.  
  427. /*****************************************************************************
  428. * DESCRIPTION:                                                               *
  429. *   Combining three geometric objects, by simply concat. their polygon.      *
  430. * lists. Any object may be NULL in which only the other two are merged.         *
  431. *                                                                            *
  432. * PARAMETERS:                                                                *
  433. *   PObj1, PObj2, PObj3: The three objects to concatenate.                   *
  434. *                                                                            *
  435. * RETURN VALUE:                                                              *
  436. *   IPObjectStruct: Concatenated object.                                     *
  437. *****************************************************************************/
  438. static IPObjectStruct *BooleanCombineThreeObjs(IPObjectStruct *PObj1,
  439.                            IPObjectStruct *PObj2,
  440.                            IPObjectStruct *PObj3)
  441. {
  442.     IPPolygonStruct *Pl;
  443.  
  444.     if (PObj1 != NULL) {
  445.     CleanUpPolygonList(&PObj1 -> U.Pl);
  446.     if (PObj1 -> U.Pl == NULL) {
  447.         IPFreeObject(PObj1);
  448.         PObj1 = NULL;
  449.     }
  450.     }
  451.     if (PObj2 != NULL) {
  452.     CleanUpPolygonList(&PObj2 -> U.Pl);
  453.     if (PObj2 -> U.Pl == NULL) {
  454.         IPFreeObject(PObj2);
  455.         PObj2 = NULL;
  456.     }
  457.     }
  458.     if (PObj3 != NULL) {
  459.     CleanUpPolygonList(&PObj3 -> U.Pl);
  460.     if (PObj3 -> U.Pl == NULL) {
  461.         IPFreeObject(PObj3);
  462.         PObj3 = NULL;
  463.     }
  464.     }
  465.  
  466.     if (PObj1 == NULL) {
  467.     PObj1 = PObj2;
  468.     PObj2 = PObj3;
  469.     PObj3 = NULL;
  470.     }
  471.     if (PObj2 == NULL) {
  472.     PObj2 = PObj3;
  473.     PObj3 = NULL;
  474.     }
  475.  
  476.     if (PObj2 != NULL) {
  477.     /* Concat the polygons of PObj2 after the polygons of PObj1. */
  478.     Pl = PObj1 -> U.Pl;
  479.     while (Pl -> Pnext != NULL)
  480.         Pl = Pl -> Pnext;
  481.     Pl -> Pnext = PObj2 -> U.Pl;  /* Concat. the polygons into one list. */
  482.     PObj2 -> U.Pl = NULL;        /* And release the second object header. */
  483.     IPFreeObject(PObj2);
  484.  
  485.         if (PObj3 != NULL) {
  486.         /* Concat the polygons of PObj3 after the polygons of PObj1/2. */
  487.         while (Pl -> Pnext != NULL)
  488.         Pl = Pl -> Pnext;
  489.         Pl -> Pnext = PObj3 -> U.Pl;  /* Concat. polygons into one list. */
  490.         PObj3 -> U.Pl = NULL;   /* And release the second object header. */
  491.         IPFreeObject(PObj3);
  492.         }
  493.     }
  494.  
  495.     return PObj1;
  496. }
  497.  
  498. /*****************************************************************************
  499. * DESCRIPTION:                                                               *
  500. *   If required (I.e. Object "COPLANAR" is set to TRUE) search all coplanar  *
  501. * polygons in PObj1/2 and invoke the necessary two dimenstional Boolean.     *
  502. *                                                                            *
  503. * PARAMETERS:                                                                *
  504. *   PObj1, PObj2: Two objects to search for coplanar polygons.               *
  505. *   BoolOper:     Type of Boolean operation to be performed between PObj1/2. *
  506. *                                                                            *
  507. * RETURN VALUE:                                                              *
  508. *   IPObjectStruct:   The resulting Boolean operation.                       *
  509. *****************************************************************************/
  510. static IPObjectStruct *BooleanCoplanar(IPObjectStruct *PObj1,
  511.                        IPObjectStruct *PObj2,
  512.                        BoolOperType BoolOper)
  513. {
  514.     MatrixType RotMat;
  515.     IPObjectStruct *PObj;
  516.     IPPolygonStruct *Pl, *PlTmp, *Pl1, *Pl2, *Pl1XY, *Pl2XY, *Pl1XYR, *Pl2XYR,
  517.     *PlOut = NULL;
  518.  
  519.     if (!BoolHandleCoplanarPoly)
  520.     return NULL;
  521.  
  522.     for ( Pl1 = PObj1 -> U.Pl; Pl1 != NULL; Pl1 = Pl1 -> Pnext) {
  523.         for ( Pl2 = PObj2 -> U.Pl; Pl2 != NULL; Pl2 = Pl2 -> Pnext) {
  524.         RealType
  525.         *Plane1 = Pl1 -> Plane,
  526.         *Plane2 = Pl2 -> Plane;
  527.         int Shared = BOOL_APX_EQ(Plane1[0], Plane2[0]) &&
  528.                  BOOL_APX_EQ(Plane1[1], Plane2[1]) &&
  529.                  BOOL_APX_EQ(Plane1[2], Plane2[2]) &&
  530.                  BOOL_APX_EQ(Plane1[3], Plane2[3]),
  531.         AntiShared = BOOL_APX_EQ(Plane1[0], -Plane2[0]) &&
  532.                  BOOL_APX_EQ(Plane1[1], -Plane2[1]) &&
  533.                  BOOL_APX_EQ(Plane1[2], -Plane2[2]) &&
  534.                  BOOL_APX_EQ(Plane1[3], -Plane2[3]);
  535.  
  536.         if (!Shared && !AntiShared) {
  537.         /* The two polygons are not coplanar, do not intersect. */
  538.         continue;
  539.         }
  540.  
  541.         if (Shared) {
  542.         switch (BoolOper) {
  543.             case BOOL_OPER_AND:
  544.             case BOOL_OPER_OR:
  545.             case BOOL_OPER_SUB:
  546.             GenRotateMatrix(RotMat, Pl1 -> Plane);
  547.             Pl1XY = ComputeRotatedPolys(Pl1, TRUE, RotMat);
  548.             Pl2XY = ComputeRotatedPolys(Pl2, TRUE, RotMat);
  549.             /* Find the inverse matrix. */
  550.             if (!MatInverseMatrix(RotMat, RotMat))
  551.                 IritFatalError("BooleanCoplanar: Inverse matrix does not exists");
  552.  
  553.             if ((Pl = Boolean2D(Pl1XY, Pl2XY, BoolOper)) != NULL) {
  554.                 Pl = ComputeRotatedPolys(Pl, FALSE, RotMat);
  555.                 for (PlTmp = Pl;
  556.                  PlTmp -> Pnext != NULL;
  557.                  PlTmp = PlTmp -> Pnext);
  558.                 PlTmp -> Pnext = PlOut;
  559.                 PlOut = Pl;
  560.             }
  561.  
  562.             IPFreePolygonList(Pl1XY);
  563.             IPFreePolygonList(Pl2XY);
  564.             break;
  565.  
  566.             default:
  567.                 IritFatalError("BooleanCoplanar: Unsupported Boolean operation BooleanCoplanar");
  568.                 return NULL;
  569.         }
  570.         }
  571.         else if (AntiShared) {
  572.         switch (BoolOper) {
  573.             case BOOL_OPER_AND:
  574.             case BOOL_OPER_SUB:
  575.             IritWarningError("Antishared coplanar polygons are ignored.");
  576.             break;
  577.  
  578.             case BOOL_OPER_OR:
  579.             GenRotateMatrix(RotMat, Pl1 -> Plane);
  580.             Pl1XY = ComputeRotatedPolys(Pl1, TRUE, RotMat);
  581.             Pl1XYR = CopyPolygonList(Pl1XY);
  582.             IritPrsrReverseVrtxList(Pl1XYR);
  583.             Pl2XY = ComputeRotatedPolys(Pl2, TRUE, RotMat);
  584.             Pl2XYR = CopyPolygonList(Pl2XY);
  585.             IritPrsrReverseVrtxList(Pl2XYR);
  586.  
  587.             if (!MatInverseMatrix(RotMat, RotMat))
  588.                 IritFatalError("BooleanCoplanar: Inverse matrix does not exists");
  589.  
  590.             if ((Pl = Boolean2D(Pl1XY, Pl2XYR, BOOL_OPER_SUB)) != NULL) {
  591.                 Pl = ComputeRotatedPolys(Pl, FALSE, RotMat);
  592.                 for (PlTmp = Pl;
  593.                  PlTmp -> Pnext != NULL;
  594.                  PlTmp = PlTmp -> Pnext);
  595.                 PlTmp -> Pnext = PlOut;
  596.                 PlOut = Pl;
  597.             }
  598.             if ((Pl = Boolean2D(Pl2XY, Pl1XYR, BOOL_OPER_SUB)) != NULL) {
  599.                 Pl = ComputeRotatedPolys(Pl, FALSE, RotMat);
  600.                 for (PlTmp = Pl;
  601.                  PlTmp -> Pnext != NULL;
  602.                  PlTmp = PlTmp -> Pnext);
  603.                 PlTmp -> Pnext = PlOut;
  604.                 PlOut = Pl;
  605.             }
  606.  
  607.             IPFreePolygonList(Pl1XY);
  608.             IPFreePolygonList(Pl2XY);
  609.             IPFreePolygonList(Pl1XYR);
  610.             IPFreePolygonList(Pl2XYR);
  611.             break;
  612.  
  613.             default:
  614.                 IritFatalError("BooleanCoplanar: Unsupported Boolean operation BooleanCoplanar");
  615.                 return NULL;
  616.         }
  617.         }
  618.     }
  619.     }
  620.  
  621.     PObj = IPAllocObject("", IP_OBJ_POLY, NULL);
  622.     PObj -> U.Pl = PlOut;
  623.     return PObj;
  624. }
  625.  
  626. /*****************************************************************************
  627. * DESCRIPTION:                                                               *
  628. *   Routine to optionally copy (if CpolyOnePl) a single polygon and rotate   *
  629. * according to the rotation matrix provided. If, however, CopyOnePl is False *
  630. * all polygons in list are converted.                         *
  631. *                                                                            *
  632. * PARAMETERS:                                                                *
  633. *   Pl:             Polygon(s) to transform.                                 *
  634. *   CopyOnePl:      Should we copy?                                          *
  635. *   RotMat:         Transformation matrix.                                   *
  636. *                                                                            *
  637. * RETURN VALUE:                                                              *
  638. *   IPPolygonStruct: Transformed polygon(s).                                 *
  639. *****************************************************************************/
  640. static IPPolygonStruct *ComputeRotatedPolys(IPPolygonStruct *Pl,
  641.                         int CopyOnePl,
  642.                         MatrixType RotMat)
  643. {
  644.     IPVertexStruct *V, *VHead;
  645.     IPPolygonStruct *PlNext, *PlTemp,
  646.     *PlOut = NULL;
  647.  
  648.     while (Pl != NULL) {
  649.     PlNext = Pl -> Pnext;
  650.  
  651.     if (CopyOnePl) {
  652.         PlTemp = IPAllocPolygon(Pl -> Count, Pl -> Tags,
  653.                     CopyVertexList(Pl -> PVertex), NULL);
  654.         PLANE_COPY(PlTemp ->Plane, Pl -> Plane);
  655.         Pl = PlTemp;
  656.     }
  657.  
  658.     V = VHead = Pl -> PVertex;
  659.     do {                    /* Transform the polygon itself. */
  660.         PointType PTemp;
  661.  
  662.         PT_ADD(PTemp, V -> Coord, V -> Normal);
  663.  
  664.         MatMultVecby4by4(V -> Coord, V -> Coord, RotMat);
  665.  
  666.         MatMultVecby4by4(PTemp, PTemp, RotMat);   /* Update normal. */
  667.         PT_SUB(V -> Normal, PTemp, V -> Coord);
  668.         PT_NORMALIZE(V -> Normal);
  669.  
  670.         V = V -> Pnext;
  671.     }
  672.     while (V != NULL && V != VHead);
  673.  
  674.     Pl -> Pnext = PlOut;
  675.     PlOut = Pl;
  676.  
  677.     if (CopyOnePl)
  678.         break;
  679.     else
  680.         Pl = PlNext;
  681.     }
  682.  
  683.     return PlOut;
  684. }
  685.  
  686. /*****************************************************************************
  687. * DESCRIPTION:                                                               *
  688. *   Routine that is called from the floating point package in case of fatal  *
  689. * floating point error. Print error message, and quit the Boolean module.    *
  690. *                                                                            *
  691. * PARAMETERS:                                                                *
  692. *   Type:       of exception.                                                *
  693. *                                                                            *
  694. * RETURN VALUE:                                                              *
  695. *   void                                                                     *
  696. *****************************************************************************/
  697. static void BooleanFPE(int Type)
  698. {
  699.     char Line[LINE_LEN];
  700.  
  701.     sprintf(Line, "Floating point error %d.", Type);
  702.     IritWarningError(Line);
  703.  
  704.     FatalErrorType = FTL_BOOL_FPE;
  705.  
  706.     longjmp(LclLongJumpBuffer, 1);
  707. }
  708.  
  709. /*****************************************************************************
  710. * DESCRIPTION:                                                               M
  711. *   Controls if intersection curves or full Boolean operation is to be       M
  712. * performed.                                     M
  713. *                                                                            *
  714. * PARAMETERS:                                                                M
  715. *   OutputInterCurve:  If TRUE only intersection curves are computed, If     M
  716. *                      false, full blown Boolean is applied.                 M
  717. *                                                                            *
  718. * RETURN VALUE:                                                              M
  719. *   void                                                                     M
  720. *                                                                            *
  721. * KEYWORDS:                                                                  M
  722. *   BoolSetOutputInterCurve, Booleans                                        M
  723. *****************************************************************************/
  724. void BoolSetOutputInterCurve(int OutputInterCurve)
  725. {
  726.     BoolOutputInterCurve = OutputInterCurve;
  727. }
  728.  
  729. /*****************************************************************************
  730. * DESCRIPTION:                                                               M
  731. *   Controls if coplanar polygons should be handled or not.                 M
  732. *                                                                            *
  733. * PARAMETERS:                                                                M
  734. *   HandleCoplanarPoly:  If TRUE, coplanar polygons are handled.             M
  735. *                                                                            *
  736. * RETURN VALUE:                                                              M
  737. *   void                                                                     M
  738. *                                                                            *
  739. * KEYWORDS:                                                                  M
  740. *   BoolSetHandleCoplanarPoly, Booleans                                      M
  741. *****************************************************************************/
  742. void BoolSetHandleCoplanarPoly(int HandleCoplanarPoly)
  743. {
  744.     BoolHandleCoplanarPoly = HandleCoplanarPoly;
  745. }
  746.  
  747. /*****************************************************************************
  748. * DESCRIPTION:                                                               *
  749. *   Routine that is called by the bool-low module in fatal error cases.      *
  750. * Will print error message and long jump using LclLongJumpBuffer.         *
  751. *                                                                            *
  752. * PARAMETERS:                                                                *
  753. *   ErrorType:   Type of error.                                              *
  754. *                                                                            *
  755. * RETURN VALUE:                                                              *
  756. *   void                                                                     *
  757. *****************************************************************************/
  758. void FatalBooleanError(int ErrorType)
  759. {
  760.     char s[LINE_LEN_LONG];
  761.  
  762.     FatalErrorType = ErrorType;
  763.  
  764.     switch (ErrorType) {
  765.     case FTL_BOOL_NO_INTER:
  766.         /* If operation is union (OR), then if no intersection we assume */
  767.         /* the objects have no common volume and simply combine them!    */
  768.         if (BooleanOperation != BOOL_OPER_OR) {
  769.         sprintf(s, "Boolean: %s",
  770.             "Objects do not intersect - Empty object result");
  771.         IritWarningError(s);
  772.         }
  773.         break;
  774.     default:
  775.         sprintf(s, "Boolean: Undefined Fatal Error (%d !?)", ErrorType);
  776.         IritWarningError(s);
  777.         break;
  778.     }
  779.  
  780.     longjmp(LclLongJumpBuffer, 1);
  781. }
  782.  
  783. #ifdef DEBUG2
  784.  
  785. /*****************************************************************************
  786. * DESCRIPTION:                                                               *
  787. *   Prints the content of the given vertex list, to standard output.         *
  788. *                                                                            *
  789. * PARAMETERS:                                                                *
  790. *   V:      Vertex list to print.                                            *
  791. *                                                                            *
  792. * RETURN VALUE:                                                              *
  793. *   void                                                                     *
  794. *****************************************************************************/
  795. static void PrintVrtxList(IPVertexStruct *V)
  796. {
  797.     IPVertexStruct
  798.     *VHead = V;
  799.  
  800.     do {
  801.     printf("[NORMAL %8lf %8lf %8lf] %12lf %12lf %12lf",
  802.            V -> Normal[0], V -> Normal[1], V -> Normal[2],
  803.            V -> Coord[0], V -> Coord[1], V -> Coord[2]);
  804.     if (IP_IS_INTERNAL_EDGE(V))
  805.         printf(" (Internal)\n");
  806.     else
  807.         printf("\n");
  808.     V = V -> Pnext;
  809.     }
  810.     while (V!= NULL && V != VHead);
  811. }
  812.  
  813. #endif /* DEBUG2 */
  814.